package com.glsc.ngateway.platform.amqp;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.common.enums.RabbitExcQueConstant;
import com.glsc.ngateway.common.api.common.ex.Result;
import com.glsc.ngateway.common.api.flowable.dto.task.message.EquipmentFlowMessageDto;
import com.glsc.ngateway.common.api.oaflow.feign.IFeignOaFlowService;
import com.glsc.ngateway.common.base.domain.mysql.gateway.oaflow.TOaFlowSyncLog;
import com.glsc.ngateway.common.base.enums.OaFlowSyncLogStatusEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowEnum;
import com.glsc.ngateway.common.base.repo.mysql.gateway.oaflow.TOaFlowSyncLogRepository;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.flow.FlowPushOaLogRepo;
import com.glsc.ngateway.platform.service.MailService;
import com.glsc.ngateway.platform.service.SystemConfigService;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.AbstractItFlowStrategy;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.IItFlowMQHandler;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.PlatformLocalConstant;
import com.rabbitmq.client.Channel;
import io.swagger.annotations.ApiParam;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 流程相关MQ接收
 */
@Component
public class FlowReceiver {

    private static final Logger logger = LoggerFactory.getLogger(FlowReceiver.class);

    @Resource
    private MailService mailService;

    @Resource
    private SystemConfigService systemConfigService;

    @Resource
    private SystemMainService systemMainService;

    @Resource
    private IFeignOaFlowService iFeignOaFlowService;

    private Map<String, IItFlowMQHandler> handlerMap;
    private Map<String, AbstractItFlowStrategy> flowStrategyMap;
    public static final ThreadLocal<String> MESSAGE_THREAD_LOCAL = new ThreadLocal<String>();
    public static final ThreadLocal<JSONObject> MSG_JSON_OBJ_THREAD_LOCAL = new ThreadLocal<JSONObject>();

    @Autowired
    public void setHandlerMap(List<IItFlowMQHandler> mqHandlerList) {
        this.handlerMap = mqHandlerList.stream()
                .filter(h -> Strings.isNotBlank(h.getMqCodeKey()))
                .collect(Collectors.toMap(IItFlowMQHandler::getMqCodeKey, handler -> handler));
    }

    @Autowired
    public void setAbstractItFlowStrategy(List<AbstractItFlowStrategy> flowStrategyList) {
        this.flowStrategyMap = flowStrategyList.stream()
                .filter(f -> Strings.isNotBlank(f.getFlowEnum().getKey()))
                .collect(Collectors.toMap(s -> s.getFlowEnum().getKey(), strategy -> strategy));
    }

    @Autowired
    private TOaFlowSyncLogRepository syncLogRepo;

    @Resource
    private FlowPushOaLogRepo flowPushOaLogRepo;

    /**
     * 自研网关内部流程相关Msg
     */
    @RabbitListener(queues = {RabbitExcQueConstant.AMPRODUCT_QUEUE_GATEWAY_FLOW_REMIND})
    @RabbitHandler
    public void processMessage(org.springframework.amqp.core.Message messageObject, Channel channel) throws UnsupportedEncodingException {
        String message = new String(messageObject.getBody());
        logger.info("AMPRODUCT_QUEUE_GATEWAY_FLOW_REMIND，收到消息，message receiver:" + message);
        EquipmentFlowMessageDto msgJsonObject = JSONObject.parseObject(message, EquipmentFlowMessageDto.class);
        //根据定义处理
        handlerMap.get(msgJsonObject.getDefineKey()).doHandle(message);
        logger.info("AMPRODUCT_QUEUE_GATEWAY_FLOW_REMIND，消息处理完毕，message：" + message);
    }

    /**
     *
     * @param messageObject
     * @param channel
     * @throws UnsupportedEncodingException
     */
    @RabbitListener(queues = {RabbitExcQueConstant.AMPRODUCT_QUEUE_OA_WORKFLOW_REMIND})
    @RabbitHandler
    public void processMessagePlatform(org.springframework.amqp.core.Message messageObject, Channel channel) throws UnsupportedEncodingException {
        String message = new String(messageObject.getBody());
        logger.info("platform，收到消息，message receiver:" + message);
        JSONObject msgObject = JSONObject.parseObject(message);
        //根据定义处理
        try {
            logger.info("任务类型为" + msgObject.get("workflowId"));
            String workflowId = msgObject.getString("workflowId");
            //根据workflowid查询对应类型
            String workflowType = systemConfigService.findConfigValueByCode(workflowId+"WorkFlowIdMap");
            switch (workflowType) {
                case PlatformLocalConstant.SYSTEM_NAME_LIST_UPDATE:
                    //解析oa流程信息
                    String oaFlowInfo = getRequestDataOrigin(msgObject.getString("requestId"),workflowId);
                    systemMainService.updateInfoByOaInfo(oaFlowInfo);
                    break;
                default:
                    mailService.sendMailToAdmin("platform消息未匹配",message);
            }
        } catch (Exception e) {
            logger.error("消息处理错误"+e);
            mailService.sendMailToAdmin("异常处理失败",JSONObject.toJSONString(e.getStackTrace()));
        }
        logger.info("platfom，消息处理完毕，message：" + message);
    }

    /**
     * oa流程同步给自研网关，oa流程结束后，调用oaflow接口，通过workflowId找到配置的exchange和queue，进行转发消息
     *
     * @see com.glsc.ngateway.oaflow.controller.OaCallController#forwardOARequest
     * (GET :/forwardOARequest)
     */
    @RabbitListener(queues = {RabbitExcQueConstant.GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT})
    @RabbitHandler
    public void processOaFlowSyncMessage(org.springframework.amqp.core.Message messageObject, Channel channel) throws Exception {
        String message = new String(messageObject.getBody());
        logger.info("GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT，收到消息，message receiver:" + message);
        JSONObject msgJsonObject = JSONObject.parseObject(message);
        //这两个字段不能为空
        String workflowId = StrUtil.trim(msgJsonObject.getString("workflowId"));
        Integer requestId = Integer.valueOf(StrUtil.trim(msgJsonObject.getString("requestId")));
        String workflowName = StrUtil.trim(msgJsonObject.getString("workflowName"));
        String description = StrUtil.trim(msgJsonObject.getString("description"));
        logger.info("开始进行 查询流程表单数据,msg:" + msgJsonObject);
        TOaFlowSyncLog log = syncLogRepo.findByRequestId(requestId);
        //根据定义处理
        if (!OaFlowSyncLogStatusEnum.isEnd(log.getStatus())) {
            flowStrategyMap.get(log.getProcessDefKey()).syncFromOaFlow(log, description);
        } else {
            logger.info("GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT，log状态{}已结束，无需处理", log.getStatus());
        }
        logger.info("GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT，消息处理完毕，message:" + message);
    }

    @RabbitListener(queues = {RabbitExcQueConstant.GATEWAY_QUEUE_FLOW_CMDB})
    @RabbitHandler
    public void processOaCmdbMessage(org.springframework.amqp.core.Message messageObject, Channel channel) throws Exception {
        String message = new String(messageObject.getBody());
        logger.info("GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT，收到消息，message receiver:" + message);
        JSONObject msgJsonObject = JSONObject.parseObject(message);
        //这两个字段不能为空
        String workflowId = StrUtil.trim(msgJsonObject.getString("workflowId"));
        String requestId = StrUtil.trim(msgJsonObject.getString("requestId"));
        String workflowName = StrUtil.trim(msgJsonObject.getString("workflowName"));
        String description = StrUtil.trim(msgJsonObject.getString("description"));
        logger.info("开始进行 查询流程表单数据,msg:" + msgJsonObject);
        Optional.ofNullable(flowPushOaLogRepo.findByWorkflowIdAndRequestId(workflowId, requestId))
                .ifPresent(log -> {
                    try {
                        flowStrategyMap.get(log.getProcessKey()).endFromOaFlow(log, description);
                    } catch (Exception e) {
                        logger.error("GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT，消息处理异常，message:{}，异常信息：", message, e.getMessage(), e);
                    }
                });
        logger.info("GATEWAY_QUEUE_FLOW_OA_MOBILE_AUDIT，消息处理完毕，message:" + message);
    }

    /**
     * OA侧设备变更流程结果同步
     */
    @RabbitListener(queues = {RabbitExcQueConstant.GATEWAY_QUEUE_FLOW_EQUIPMENT_MODIFY})
    @RabbitHandler
    public void receiveOaEquipmentModify(org.springframework.amqp.core.Message messageObject, Channel channel) {
        String message = MESSAGE_THREAD_LOCAL.get();
        JSONObject msgJsonObject = MSG_JSON_OBJ_THREAD_LOCAL.get();
        logger.info("GATEWAY_QUEUE_FLOW_EQUIPMENT_MODIFY，收到消息，message receiver:" + message);
        //这两个字段不能为空
        String workflowId = StrUtil.trim(msgJsonObject.getString("workflowId"));
        String requestId = StrUtil.trim(msgJsonObject.getString("requestId"));
        String workflowName = StrUtil.trim(msgJsonObject.getString("workflowName"));
        String description = StrUtil.trim(msgJsonObject.getString("description"));
        //根据定义处理
        flowStrategyMap.get(ITFlowEnum.EQUIPMENT_MODIFY.getKey()).doHandle(workflowId, requestId, description);
        logger.info("GATEWAY_QUEUE_FLOW_EQUIPMENT_MODIFY，消息处理完毕，message:" + message);
    }

    public String getRequestDataOrigin(@ApiParam(required = true, value = "requestId") String requestId, @ApiParam(required = true, value = "requestId") String workflowId) {
        logger.info("开始进行 查询流程表单数据,requestId=" + requestId);
        String ret = iFeignOaFlowService.getRequestDataOrigin(requestId, workflowId);
        logger.info("getRequestData接口返回：" + ret);
        return ret;
    }
}
